package com.ea.eadp.nexus.proxy.tests.identity;

import com.ea.eadp.nexus.test.common.*;
import com.ea.eadp.nexus.test.common.ApiClients.FacebookApi;
import com.ea.eadp.nexus.test.common.ApiClients.NexusConnectApi;
import com.ea.eadp.nexus.test.common.ApiClients.NexusGatewayApi;
import com.ea.nucleus.caseproperties.CaseProperties;
import com.ea.nucleus.caseproperties.Priority;
import com.ea.nucleus.caseproperties.Release;
import com.ea.nucleus.caseproperties.ReleaseFeatures.July2015;
import com.ea.nucleus.caseproperties.Status;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

@CaseProperties(
        priority = Priority.Dailies,
        release = Release.Jul2015,
        status = Status.Enable,
        features = July2015.GOPFR_1687,
        owner = "ChrisShen"
)
public class BulkPersonasSearch {
    private static String antelopeClientId = "antelope_test";
    private static String antelopeClientSecret = "antelope_test_secret";
    private static String personaNamespace = "antelope_gs";
    private static String typeAuthenticatorFacebook = "AUTHENTICATOR_FACEBOOK";
    private static String hashAlgorithm = "HmacSHA256";
    private static String hashKey = "rDjlXGsaAagQl9wN2JE0HJ0ChANwlq";
    private List<FacebookTestUser> FBusers;

    @BeforeMethod(alwaysRun = true, enabled = true)
    public void initFBusers() throws Exception {
        FBusers = new ArrayList<FacebookTestUser>();
    }

    @AfterMethod(alwaysRun = true, enabled = true)
    public void delFBusers() throws Exception {
        if (!FBusers.isEmpty()) {
            for (FacebookTestUser user : FBusers) {
                System.out.println("Delete Facebook Testuser" + user.getid());
                FacebookApi.instance().deleteFacebookTestUser(user.getid());
            }
        }
    }

    @CaseProperties(
            status = Status.Manual,
            passed = true,
            description = "You can run this test case manually if you hit the create facebook test user limitation to clean up all facebook test users"
    )
    @Test
    public void cleanUpFacebookTestUser() throws Exception {
        FacebookApi.instance().cleanUpFacebookTestUser();
    }

    @Test(groups = {"regression", "intregression"})
    public void testBulkPersonasSearch() throws Exception {
        List<String> fbExtrefList = new ArrayList<String>();
        List<String> personaList = new ArrayList<String>();
        AccessToken token = null;

        for (int i = 0; i < 3; ++i) {
            String upidToken = NexusConnectApi.instance().getUpidToken(antelopeClientId);
            String code = getAntelopeAnonymousAuthCode(upidToken);
            token = NexusConnectApi.instance().getTokenByCodeWithClientSecret(code, antelopeClientId, antelopeClientSecret);

            FacebookTestUser fbUser = FacebookApi.instance().postFacebookTestUser();
            FBusers.add(fbUser);
            fbExtrefList.add(fbUser.getid());
            String fb_token = fbUser.getaccess_token();
            String code2 = NexusConnectApi.instance().getCodeByAntelopeFacebook(antelopeClientId, fb_token);
            token = NexusConnectApi.instance().addAuthenticator(token.getAccess_token(), code2, UUID.randomUUID().toString(), antelopeClientId, antelopeClientSecret, null);
            TokenInfo tokenInfo = TestUtil.parseJson(NexusConnectApi.instance().getTokenInfo(token, null), TokenInfo.class);
            personaList.add(tokenInfo.getPersona_id());
        }

        PidInfos pidInfos = bulkPersonasSearch(typeAuthenticatorFacebook, personaNamespace, fbExtrefList, token);
        for (PidIdInfo info : pidInfos.getPidInfos().getPidInfo()) {
            Assert.assertEquals(info.getPidType(), typeAuthenticatorFacebook);
            Assert.assertTrue(fbExtrefList.contains(info.getExternalRefValue()));
            Assert.assertTrue(personaList.contains(info.getPersonaId()));
        }
    }

    @Test(groups = {"regression", "intregression"})
    public void testBulkPersonasSearchWithNonAntelopeFbUser() throws Exception {
        List<String> fbExtrefList = new ArrayList<String>();
        AccessToken token = null;

        String upidToken = NexusConnectApi.instance().getUpidToken(antelopeClientId);
        String code = getAntelopeAnonymousAuthCode(upidToken);
        token = NexusConnectApi.instance().getTokenByCodeWithClientSecret(code, antelopeClientId, antelopeClientSecret);

        FacebookTestUser fbUser = FacebookApi.instance().postFacebookTestUser();
        FBusers.add(fbUser);
        fbExtrefList.add(fbUser.getid());
        String fb_token = fbUser.getaccess_token();
        String code2 = NexusConnectApi.instance().getCodeByAntelopeFacebook(antelopeClientId, fb_token);
        token = NexusConnectApi.instance().addAuthenticator(token.getAccess_token(), code2, UUID.randomUUID().toString(), antelopeClientId, antelopeClientSecret, null);
        TokenInfo tokenInfo = TestUtil.parseJson(NexusConnectApi.instance().getTokenInfo(token, null), TokenInfo.class);

        fbUser = FacebookApi.instance().postFacebookTestUser();
        FBusers.add(fbUser);
        fbExtrefList.add(fbUser.getid());
        PidInfos pidInfos = bulkPersonasSearch(typeAuthenticatorFacebook, personaNamespace, fbExtrefList, token);
        Assert.assertEquals(pidInfos.getPidInfos().getPidInfo().size(), 1);
        Assert.assertEquals(pidInfos.getPidInfos().getPidInfo().get(0).getPersonaId(), tokenInfo.getPersona_id());
    }

    @Test(groups = {"regression", "intregression"})
    public void testBulkPersonasSearchWithNegativeInput() throws Exception {
        List<String> fbExtrefList = new ArrayList<String>();
        AccessToken token = null;

        String upidToken = NexusConnectApi.instance().getUpidToken(antelopeClientId);
        String code = getAntelopeAnonymousAuthCode(upidToken);
        token = NexusConnectApi.instance().getTokenByCodeWithClientSecret(code, antelopeClientId, antelopeClientSecret);

        FacebookTestUser fbUser = FacebookApi.instance().postFacebookTestUser();
        FBusers.add(fbUser);
        fbExtrefList.add(fbUser.getid());
        String fb_token = fbUser.getaccess_token();
        String code2 = NexusConnectApi.instance().getCodeByAntelopeFacebook(antelopeClientId, fb_token);
        token = NexusConnectApi.instance().addAuthenticator(token.getAccess_token(), code2, UUID.randomUUID().toString(), antelopeClientId, antelopeClientSecret, null);

        fbUser = FacebookApi.instance().postFacebookTestUser();
        FBusers.add(fbUser);
        fbExtrefList.add(fbUser.getid());

        String errorString = bulkPersonasSearchError(typeAuthenticatorFacebook, "invalidNamespace", fbExtrefList, token);
        Assert.assertTrue(errorString.contains("NOT_ALLOWED"));
        errorString = bulkPersonasSearchError("invalid_type", personaNamespace, fbExtrefList, token);
        Assert.assertTrue(errorString.contains("INVALID_PID_TYPE"));
    }

    private PidInfos bulkPersonasSearch(String pidType, String personaNamespace, List<String> values, AccessToken token) throws Exception {
        String valuesString = TestUtil.connectStringByComma(values);
        valuesString = "[" + valuesString + "]";
        String payload = "{\n" +
                "\"pidType\":\"" + pidType + "\",\n" +
                "\"personaNamespace\":\"" + personaNamespace + "\",\n" +
                "\"values\":" + valuesString + "\n}";
        HashMap<String, String> context = new HashMap<String, String>();
        String pidInfosString = NexusGatewayApi.instance().post(NexusGatewayApiEnum.persona_multisearch_get, context, token, payload, true);
        return TestUtil.parseJson(pidInfosString, PidInfos.class);
    }

    private String bulkPersonasSearchError(String pidType, String personaNamespace, List<String> values, AccessToken token) throws Exception {
        String valuesString = TestUtil.connectStringByComma(values);
        valuesString = "[" + valuesString + "]";
        String payload = "{\n" +
                "\"pidType\":\"" + pidType + "\",\n" +
                "\"personaNamespace\":\"" + personaNamespace + "\",\n" +
                "\"values\":" + valuesString + "\n}";
        HashMap<String, String> context = new HashMap<String, String>();
        return NexusGatewayApi.instance().post(NexusGatewayApiEnum.persona_multisearch_get, context, token, payload, false);
    }

    private String getAntelopeAnonymousAuthCode(String upidToken) throws Exception {
        return getAntelopeAnonymousAuthCode(upidToken, antelopeClientId);
    }

    private String getAntelopeAnonymousAuthCode(String upidToken, String clientId) throws Exception {
        String payload = getAntelopeAnonymousLoginPayload(upidToken);
        String hashPayload = payload + "." + getHash(payload);
        String code = NexusConnectApi.instance().getCodeByAntelopeAnonymous(clientId, hashPayload);
        return code;
    }

    private String getAntelopeAnonymousLoginPayload(String upidToken) throws Exception {
        return getAntelopeAnonymousLoginPayload(upidToken, "v1", "v1", 0);
    }

    private String getAntelopeAnonymousLoginPayload(String anonymousSecret, String algorithmVersion, String secretVersion, int secsBefore) throws Exception {
        return TestUtil.getAnonymousLoginPayload(anonymousSecret, algorithmVersion, secretVersion, secsBefore,null,null);
    }

    private String getHash(String message) throws Exception {
        return TestUtil.getHash(message, hashAlgorithm, hashKey);
    }
}
